package org.threadly.litesockets; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.SelectableChannel; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; /** * A Simple TCP server. * */ public class TCPServer extends Server { private final ServerSocketChannel socket; private volatile SSLContext sslCtx; private volatile String hostName; private volatile boolean doHandshake = false; /** * Creates a new TCP Listen socket on the passed host/port. This is Listen port is created * immediately and will throw an exception if for any reason it can't be opened. * * @param host The host address/interface to create this listen port on. * @param port The port to use for the listen port. * @throws IOException This is throw if for any reason we can't create the listen port. */ protected TCPServer(final SocketExecuter se, final String host, final int port) throws IOException { super(se); socket = ServerSocketChannel.open(); socket.socket().setReuseAddress(true); socket.socket().bind(new InetSocketAddress(host, port), 100); socket.configureBlocking(false); } /** * This allows you to provide an already existing {@link ServerSocketChannel}. It must already be open. * * @param server The {@link ServerSocketChannel} to be used by this TCPServer. * @throws IOException If anything is wrong with the provided {@link ServerSocketChannel} this will be thrown. */ protected TCPServer(final SocketExecuter se, final ServerSocketChannel server) throws IOException{ super(se); server.configureBlocking(false); socket = server; } @Override public ServerSocketChannel getSelectableChannel() { return socket; } @Override public void close() { if(this.setClosed()) { getSocketExecuter().stopListening(this); try { socket.close(); } catch (IOException e) { //We dont care } finally { callClosers(); } } } @Override public WireProtocol getServerType() { return WireProtocol.TCP; } @Override public void acceptChannel(final SelectableChannel c) { this.getSocketExecuter().getThreadScheduler().execute(new Runnable() { public void run() { try { final TCPClient client = getSocketExecuter().createTCPClient((SocketChannel)c); if(sslCtx != null) { SSLEngine ssle; if(hostName == null) { ssle = sslCtx.createSSLEngine(client.getLocalSocketAddress().getHostName(), client.getLocalSocketAddress().getPort()); } else { ssle = sslCtx.createSSLEngine(hostName, client.getLocalSocketAddress().getPort()); } ssle.setUseClientMode(false); client.setSSLEngine(ssle); if(doHandshake) { client.startSSL(); } } if(getClientAcceptor() != null) { getClientAcceptor().accept(client); } } catch (IOException e) { //We dont care, client closed before we could do anything with it. } } }); } public void setSSLContext(final SSLContext sslctx) { this.sslCtx = sslctx; } public void setSSLHostName(final String name) { this.hostName = name; } public void setDoHandshake(final boolean hs) { this.doHandshake = hs; } }